package Voice;
import Voice.interfere.VoiceChatCallback;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.TargetDataLine;

public class VoiceChatUtil {

    // 用于存储客户端连接的Socket
    private static List<Socket> clientSockets = new ArrayList<>();
    // 用于存储所有客户端Socket的并发安全队列
    private static ConcurrentLinkedQueue<Socket> allClientSockets = new ConcurrentLinkedQueue<>();


    // 定义函数实现语音聊天功能，带有五个可选参数
    public static void voiceChatFunction(String uid, String ipAddress, int sendPort, int receivePort, VoiceChatCallback callback) {
        if (uid == null && ipAddress == null && sendPort == 0 && receivePort == 0 && callback == null) {
            String[] args = null;
            try {
                args = new String[]{System.getProperty("user.name")};
                uid = args[0];
                ipAddress = "127.0.0.1";
                sendPort = 8888;
                receivePort = 8889;
                // 创建默认回调函数实例，这里只是示例，可根据实际需求完善
                callback = new VoiceChatCallback() {
                    @Override
                    public void onChatFinished(byte[] buffer) {
                        System.out.println("语音聊天已结束");
                    }
                };
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 接收线程
        int finalReceivePort = receivePort;
        Thread receiveThread = new Thread(() -> {
            try {
                System.out.println("即将创建ServerSocket，监听端口: " + finalReceivePort);
                ServerSocket serverSocket = new ServerSocket(finalReceivePort);
                System.out.println("ServerSocket创建成功，已开始监听端口: " + finalReceivePort);
                System.out.println("接收端已启动，等待客户端连接...");
                while (true) {
                    Socket clientSocket = serverSocket.accept();
                    System.out.println("有新客户端连接：" + clientSocket.getInetAddress());
                    boolean isReconnect = false;
                    for (Socket existingSocket : clientSockets) {
                        if (existingSocket.getInetAddress().equals(clientSocket.getInetAddress())) {
                            isReconnect = true;
                    break;
                        }
                    }
                    ClientHandler clientHandler = new ClientHandler(clientSocket, isReconnect);
                    new Thread(clientHandler).start();
                }
            } catch (IOException e) {
                System.out.println("创建ServerSocket失败，错误信息: " + e.getMessage());
                e.printStackTrace();
            }
        });

        // 发送线程
        String finalIpAddress = ipAddress;
        int finalSendPort = sendPort;
        Thread sendThread = new Thread(() -> {
            try {
                Socket socket = new Socket(finalIpAddress, finalSendPort);
                AudioFormat audioFormat = new AudioFormat(44100, 16, 1, true, false);

                // 启动采集和发送语音数据的逻辑
                System.out.println("调用麦克风成功");
                OutputStream outputStream = socket.getOutputStream();
                DataLine.Info dataLineInfo = new DataLine.Info(TargetDataLine.class, audioFormat);
                TargetDataLine targetDataLine = (TargetDataLine) AudioSystem.getLine(dataLineInfo);
                targetDataLine.open(audioFormat);
                targetDataLine.start();
                byte[] buffer = new byte[2048];
                int bytesRead;
                while (true) {
                    bytesRead = targetDataLine.read(buffer, 0, buffer.length);
                    if (bytesRead!= -1) {
                        outputStream.write(buffer, 0, bytesRead);
                    } else {
                        break;
                    }
                }
                targetDataLine.close();

                // 关闭发送数据的Socket连接
                socket.close();
            } catch (Exception e) {
                handleDisconnect(e);
            }
        });

        // 新增扬声器处理线程
        Thread speakerThread = new Thread(() -> {
            try {
                Socket socket = new Socket(finalIpAddress, finalSendPort);
                AudioFormat audioFormat = new AudioFormat(44100, 16, 1, true, false);

                // 启动接收和播放语音数据的逻辑，重新定义dataLineInfo
                InputStream inputStream = socket.getInputStream();
                DataLine.Info dataLineInfoForSpeaker = new DataLine.Info(SourceDataLine.class, audioFormat);
                SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem.getLine(dataLineInfoForSpeaker);
                sourceDataLine.open(audioFormat);
                sourceDataLine.start();
                byte[] buffer = new byte[1024];

                while (true) {
                    System.out.println("即将从网络输入流中读取音频数据");
                    int bytesRead = inputStream.read(buffer);
                    System.out.println("已从网络输入流中读取 " + bytesRead + " 字节的音频数据");
                    if (bytesRead!= -1) {
                        System.out.println("即将把 " + bytesRead + " 字节的音频数据写入播放设备");
                        sourceDataLine.write(buffer, 0, bytesRead);
                        System.out.println("已成功将音频数据写入播放设备");
                    } else if (bytesRead == 0) {
                        System.out.println("读取到的音频数据量为0，可能是网络传输问题或客户端未发送有效数据");
                    } else {
                        break;
                    }
                }
                if (sourceDataLine.isOpen()) {
                    sourceDataLine.drain();
                    sourceDataLine.close();
                }

                // 关闭接收数据的Socket连接
                socket.close();
            } catch (Exception e) {
                handleDisconnect(e);
            }
        });


        receiveThread.start();
        sendThread.start();
        speakerThread.start();

        try {
            receiveThread.join();
            sendThread.join();
            speakerThread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

// 如果回调函数不为空，执行回调函数相关操作
        if (callback!= null) {
            // 这里假设回调函数接口的onChatFinished方法需要传入一个字节缓冲区数据，具体根据实际情况修改
            byte[] buffer = new byte[1024];
            callback.onChatFinished(buffer);
        }
    }

    // 处理连接断开的情况
    private static void handleDisconnect(Exception e) {
        if (e instanceof IOException && ((IOException) e).getMessage().contains("Connection reset by peer")) {
            try {
                // 这里假设可以获取到当前连接的Socket并关闭它，实际可能需要根据具体情况调整
                Socket socket = null; // 需要根据实际情况获取到对应的Socket
                socket.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            System.out.println("连接已断开，等待重新连接...");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            // 这里可以添加重新连接的逻辑，比如重新调用voiceChatFunction等
        } else {
            e.printStackTrace();
        }
    }

    // ClientHandler类，用于处理客户端连接
    private static class ClientHandler implements Runnable {
        private Socket clientSocket;
        private boolean isReconnected;
        private final byte[] buffer = new byte[2048];
        private int bufferIndex = 0;

        public ClientHandler(Socket clientSocket, boolean isReconnected) {
            this.clientSocket = clientSocket;
            this.isReconnected = isReconnected;
            if (!isReconnected) {
                allClientSockets.add(clientSocket);
            }
        }

        @Override
        public void run() {
            try {
                InputStream inputStream = clientSocket.getInputStream();
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer, bufferIndex, buffer.length - bufferIndex))!= -1) {
                    bufferIndex += bytesRead;
                    if (bufferIndex >= buffer.length) {
                        // 缓冲区已满，进行数据转发
                        for (Socket otherSocket : allClientSockets) {
                            if (otherSocket!= clientSocket && otherSocket.isConnected()) {
                                try {
                                    OutputStream outputStream = otherSocket.getOutputStream();
                                    outputStream.write(buffer, 0, buffer.length);
                                } catch (IOException e) {
                                    allClientSockets.remove(otherSocket);
                                }
                            }
                        }
                        bufferIndex = 0;
                    }
                }
                // 如果还有剩余数据未发送，进行发送
                if (bufferIndex > 0) {
                    for (Socket otherSocket : allClientSockets) {
                        if (otherSocket!= clientSocket && otherSocket.isConnected()) {
                            try {
                                OutputStream outputStream = otherSocket.getOutputStream();
                                outputStream.write(buffer, 0, bufferIndex);
                            } catch (IOException e) {
                                allClientSockets.remove(otherSocket);
                            }
                        }
                    }
                }
            } catch (IOException e) {
                handleDisconnect(e);
            }
        }
    }
}